// poj3133
// 题意：
// 给定一个n*m(<=9*9)的棋盘，有两个2, 两个3, 求两条路，分别连接两个2, 
// 两个3, 路径不相交，求最短长度和。
//
// 题解：
// 就是简单路径的插头dp，不过因为确定了起点和终点，而且不是回路，所以不需要
// 维护联通性信息，就不需要左右括号之类的。
//
// 狂转移。最后再更新到最后一个终点位置并且当状态为0的时候更新答案。
//
// run: $exec < input
// opt: 0
// flag: -g
#include <iostream>
#include <iomanip>

int const  inf = 1 << 30;
int const maxn = 10;
int a[maxn][maxn];
int n, m, now, prev;

struct hash_table
{
	int const static maxsize = 20000;
	int hash[maxsize], state[maxsize], dp[maxsize];
	int count;

	void clear()
	{
		count = 0;
		std::fill(hash, hash + maxsize, 0);
		std::fill(state, state + maxsize, -1);
		std::fill(dp, dp + maxsize, inf);
	}

	int & operator[](int state_)
	{
		int p;
		for (int i = state_ % maxsize; ; i++) {
			if (i == maxsize) i = 0;
			if (!hash[i]) { hash[i] = ++count; state[count] = state_; }
			if (state[hash[i]] == state_) { p = hash[i]; break; }
		}
		return dp[p];
	}
};

hash_table f[2];
int ans, tot;

int get(int st, int p) { return (st >> ((p - 1) << 1)) & 3; }
void change(int & st, int p, int v)
{
	int w = (p - 1) << 1;
	st &= (~0) ^ (3 << w);
	st |= v << w;
}

void print(int st)
{
	for (int i = 1; i <= m + 1; i++)
		std::cout << get(st, i);
}

void dp(int i, int j)
{
	now ^= 1; prev ^= 1;
	f[now].clear();
	if (a[i][j] > 1) tot++;
	for (int t = 1; t <= f[prev].count; t++) {
		int st = f[prev].state[t];
		int v = f[prev].dp[t];
		int left = get(st, j);
		int up = get(st, j + 1);
#if DEBUG
		std::cerr << "(" << i << ", " << j << ")  = " << std::setw(3) << v << "  left = " << left << "  up = " << up << " ";
		print(st);
		std::cout << "\n";
#endif

		if (!a[i][j]) {
			if (!left && !up) {
				f[now][st] = std::min(f[now][st], v);
				if (i != n && j != m) {
					change(st, j, 1); change(st, j + 1, 1);
					f[now][st] = std::min(f[now][st], v + 1);
					change(st, j, 2); change(st, j + 1, 2);
					f[now][st] = std::min(f[now][st], v + 1);
				}
			} else if ((left && !up) || (!left && up)) {
				if (i != n) {
					change(st, j, left + up);
					change(st, j + 1, 0);
					f[now][st] = std::min(f[now][st], v + 1);
				}
				if (j != m) {
					change(st, j, 0);
					change(st, j + 1, left + up);
					f[now][st] = std::min(f[now][st], v + 1);
				}
			} else if (left == up) {
				change(st, j, 0);
				change(st, j + 1, 0);
				f[now][st] = std::min(f[now][st], v + 1);
				if (tot >= 4 && !st) ans = std::min(ans, f[now][st]);
			}
		} else if (a[i][j] == 1) {
			if (!left && !up) f[now][st] = std::min(f[now][st], v);
		} else if (a[i][j] > 1) {
			if ((left == a[i][j] - 1 && !up) || (!left && up == a[i][j] - 1)) {
				change(st, j, 0);
				change(st, j + 1, 0);
				f[now][st] = std::min(f[now][st], v + 1);
				if (tot >= 4 && !st) ans = std::min(ans, f[now][st]);
			} else if (!left && !up) {
				if (i != n) {
					change(st, j, a[i][j] - 1);
					change(st, j + 1, 0);
					f[now][st] = std::min(f[now][st], v + 1);
				}
				if (j != m) {
					change(st, j, 0);
					change(st, j + 1, a[i][j] - 1);
					f[now][st] = std::min(f[now][st], v + 1);
				}
			}
		}
	}
}

int main()
{
	while (std::cin >> n >> m && (n || m)) {
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++) std::cin >> a[i][j];
		now = 0; prev = 1; tot = 0;
		f[now].clear(); f[now][0] = 0;
		ans = inf;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) dp(i, j);
			if (i == n) continue;
			for (int j = 1; j <= f[now].count; j++)
				f[now].state[j] <<= 2;
		}
		if (ans >= inf) ans = 2;
		std::cout << ans - 2 << "\n";
	}
}

